﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Security.Cryptography;
using System;
using LitJson;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;
//打包脚本
public class ExportPackage:AssetPostprocessor
{
    //资源路径
    private static string resPath = Application.dataPath + "/AllRes/module";
    //代码路径
    private static string scriptPath = Application.dataPath + "/LuaScript/module";
    //资源包临时存放路径
    private static string tempExportPath = Application.dataPath + "/ExportAssetBundle";
    //资源包导出路径
    private static string abExportPath = tempExportPath.Replace("Assets/", "");
    //所有ab包路径
    private static string allABPath = abExportPath + "/AllAB";
    //首包资源路径
    private static string firstABPath = abExportPath + "/FirstAB";
    //压缩包存放路径
    private static string zipPath = abExportPath + "/Zip";
    //所有的资源包名字
    private static List<string> allABName = new List<string>();
    //得到指定路径下所有的文件夹数据
    private static DirectoryInfo[] GetAllDirAtPath(string path)
    {
        DirectoryInfo dir = new DirectoryInfo(path);
        return dir.GetDirectories();
    }
    //为每个文件夹设置AB属性
    private static void SetAB(int type,DirectoryInfo[] info)//type=1 资源 / type=2 代码
    {
        string abPath = null;
        for (int i = 0; i < info.Length; i++)
        {
            switch (type)
            {
                case 1:
                    abPath = "Assets/AllRes/module/"+info[i].Parent.Name+"/" + info[i].Name;
                    break;
                case 2:
                    abPath = "Assets/LuaScript/module/" + info[i].Name;
                    break;
            }
            AssetImporter asset = AssetImporter.GetAtPath(abPath);
            asset.assetBundleName = info[i].Name;
            asset.assetBundleVariant = "zxy";
            allABName.Add(info[i].Name + ".zxy");
        }
    }
    //设置导入图片packingtag
    void OnPreprocessTexture()
    {
        //自动设置类型;  
        TextureImporter textureImporter = (TextureImporter)assetImporter;
        textureImporter.textureType = TextureImporterType.Sprite;
        //自动设置打包tag;  
        string dirName = Path.GetDirectoryName(assetPath);
        string folderStr = Path.GetFileName(dirName);
        textureImporter.spritePackingTag = folderStr;
    }
    //创建临时导出文件夹
    private static void CreateTempDir(string path)
    {
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
    }
    //创建导出文件夹
    private static void CreateExportDir()
    {
        if (!Directory.Exists(abExportPath))
        {
            Directory.CreateDirectory(abExportPath);
        }
        else
        {
            Directory.Delete(abExportPath, true);
            Directory.CreateDirectory(abExportPath);
        }
        Directory.CreateDirectory(allABPath);
        Directory.CreateDirectory(firstABPath);
        Directory.CreateDirectory(zipPath);
    }
    //将资源包移动到导出文件夹
    private static void MoveAllAB()
    {
        CreateExportDir();
        for (int i = 0; i < allABName.Count; i++)
        {
            File.Move(tempExportPath + "/" + allABName[i], allABPath + "/" + allABName[i]);
        }
        allABName.Clear();
        Directory.Delete(tempExportPath, true);
        Log.LogError("--------------移动所有资源包完成--------------");
    }
    //根据路径得到文件的md5值
    private static string GetMD5(string path)
    {
        FileStream stream = new FileStream(path, FileMode.Open);
        MD5 md5 = new MD5CryptoServiceProvider();
        byte[] data = md5.ComputeHash(stream);
        stream.Close();
        return BitConverter.ToString(data).Replace("-","");
    }
    //得到一个文件夹下所有文件数据
    private static FileInfo[] GetAllFileAtPath(string path)
    {
        DirectoryInfo dir = new DirectoryInfo(path);
        return dir.GetFiles();
    }
    //生成json数据
    private static void CreateJson()
    {
        JsonData allABJson = new JsonData();
        JsonData firstABJson = new JsonData();
        string version= DateTime.Now.ToString("yyyyMMdd") + DateTime.Now.ToLongTimeString().Replace(":", "");
        allABJson.version = version;
        firstABJson.version = version;
        FileInfo[] infos = GetAllFileAtPath(allABPath);
        for (int i = 0; i < infos.Length; i++)
        {
            ABItemData data = new ABItemData();
            data.name = infos[i].Name;
            data.size = infos[i].Length;
            data.md5 = GetMD5(allABPath + "/" + infos[i].Name);
            allABJson.dataList.Add(data);
            if(firstABList.Contains(infos[i].Name))
            {
                firstABJson.dataList.Add(data);
            }
        }
        string allJsonData= JsonMapper.ToJson(allABJson);
        FileStream allABStream= File.Create(allABPath + "/json.txt");
        allABStream.Close();
        File.WriteAllText(allABPath + "/json.txt", allJsonData);
        string firstJsonData= JsonMapper.ToJson(firstABJson);
        FileStream firstABStream= File.Create(firstABPath + "/json.txt");
        firstABStream.Close();
        File.WriteAllText(firstABPath + "/json.txt", firstJsonData);
        Log.LogError("------------生成Json数据完成--------------");
    }
    //资源包生成json数据类
    private class JsonData
    {
        public string version;
        public List<ABItemData> dataList=new List<ABItemData>();
    }
    //单个资源包数据类
    private struct ABItemData
    {
        public string name;
        public string md5;
        public long size;
    }
    //设置所有的ab包标签
    private static void SetAllAB()
    {
        CreateTempDir(tempExportPath);
        DirectoryInfo[] resInfo = GetAllDirAtPath(resPath);
        for (int i = 0; i < resInfo.Length; i++)
        {
            DirectoryInfo[] infos = resInfo[i].GetDirectories();
            SetAB(1, infos);
        }
        DirectoryInfo[] scriptInfo = GetAllDirAtPath(scriptPath);
        SetAB(2, scriptInfo);
        Log.LogError("---------------设置所有打包标签--------------");
    }
    //将需要的资源包移动到Streaming路径下
    private static void MoveStreaming()
    {
        if (!Directory.Exists(Application.streamingAssetsPath))
        {
            Directory.CreateDirectory(Application.streamingAssetsPath);
        }
        else
        {
            Directory.Delete(Application.streamingAssetsPath, true);
            Directory.CreateDirectory(Application.streamingAssetsPath);
        }
        CopyAllFileToDir(firstABPath, Application.streamingAssetsPath);
        Log.LogError("-----------移动资源到Streaming完成--------------");
    }
    //创建首包资源
    static List<string> firstABList = new List<string>();
    private static void MoveFirstAB()
    {
        string firstABConfig = File.ReadAllText(scriptPath + "/update/first_ab.txt");
        firstABList.Clear();
        GetABList(firstABConfig);
        for (int i = 0; i < firstABList.Count; i++)
        {
            File.Copy(allABPath + "/" + firstABList[i], firstABPath + "/" + firstABList[i]);
        }
        Log.LogError("--------------移动首包资源完成-------------");
    }
    //得到首包资源名称
    private static void GetABList(string abConfig)
    {
        int startIndex= abConfig.IndexOf('"')+1;
        int endIndex = abConfig.IndexOf('"', startIndex);
        if (startIndex > 0 && endIndex > 0)
        {
            string abName = abConfig.Substring(startIndex, endIndex-startIndex);
            firstABList.Add(abName+".zxy");
            GetABList(abConfig.Substring(endIndex + 1));
        }
        return;
    }
    //将一个文件夹下面的文件原封不动复制到另一个文件夹
    private static void CopyAllFileToDir(string path, string exportPath)
    {
        FileInfo[] infos = GetAllFileAtPath(path);
        for (int i = 0; i < infos.Length; i++)
        {
            File.Copy(path + "/" + infos[i].Name, exportPath + "/" + infos[i].Name);
        }
    }
    //打包zip
    private static void CreateZip()
    {
        ZipOutputStream stream = new ZipOutputStream(File.Create(zipPath+"/allAB.zip"));
        stream.SetLevel(1);
        AddZipEntry(allABPath, stream);
        UnZip(zipPath + "/allAB.zip", zipPath);
        Log.LogError("-------------压缩zip完成-------------");
    }
    private static void UnZip(string zipPath, string outPath)
    {
        ZipInputStream zipStream = new ZipInputStream(File.OpenRead(zipPath));
        ZipEntry zipEntry = null;
        while ((zipEntry = zipStream.GetNextEntry()) != null)
        {
            FileStream fileStream = File.Create(outPath + "/" + zipEntry.Name);
            byte[] buffer = new byte[zipEntry.Size];
            zipStream.Read(buffer, 0, buffer.Length);
            fileStream.Write(buffer, 0, buffer.Length);
            fileStream.Close();
        }
        zipStream.CloseEntry();
        zipStream.Close();
    }
    private static void AddZipEntry(string dirPath,ZipOutputStream zipStream)
    {
        string[] fileNames = Directory.GetFiles(dirPath);
        for (int i = 0; i < fileNames.Length; i++)
        {
            FileStream stream = File.OpenRead(fileNames[i]);
            byte[] buffer = new byte[stream.Length];
            stream.Read(buffer, 0, buffer.Length);
            ZipEntry zipEntry = new ZipEntry(fileNames[i].Replace(allABPath, ""));
            zipEntry.DateTime = DateTime.Now;
            zipEntry.Size = buffer.Length;
            stream.Close();
            zipStream.PutNextEntry(zipEntry);
            zipStream.Write(buffer, 0, buffer.Length);
        }
        zipStream.CloseEntry();
        zipStream.Close();
    }
    //开始打包
    [MenuItem("Tools/ExportPackage")]
    private static void ExportResAB()
    {
        allABName.Clear();
        SetAllAB();
        BuildPipeline.BuildAssetBundles(tempExportPath, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
        MoveAllAB();
        MoveFirstAB();
        CreateJson();
        MoveStreaming();
        CreateZip();
        AssetDatabase.Refresh();
        Log.LogError("-------------打包流程完毕------------");
    }
}
